/** @format */
import { resultsModel } from '../../sdk'
import { CODE_TYPES } from '../../constants'
import { logFn, recordErrorLog } from '../../utils'
import { formatDate } from '../../utils/common/date'
import { cloundAlarm } from '../../utils/common/dingTalk'

// 限制请求频率 rate单位 ms
export default function requestRateLimit(rate = 500) {
  return function (target: Object, name: string, descriptor: PropertyDescriptor) {
    const method = descriptor.value

    descriptor.value = async function (...args: any[]) {
      const recordTableName = 'c_test'
      const [context, baseInfos = {}, services = [], preCheckData = {}] = args
      const { activityId } = context.data
      const { openId } = context
      const handler = context?.cloud?.dataspace?.context?.handler

      try {
        const data = await context.cloud.dataspace.executeSql(
          `SELECT gmt_modified FROM ${recordTableName} where activity_id = ? and open_id = ? and handler = ?`,
          [activityId, openId, handler]
        )

        const handlerRecord = data?.[0]

        if (!handlerRecord) {
          context.cloud.dataspace.executeSql(
            `insert into ${recordTableName}(activity_id,open_id,handler,count) values(?,?)`,
            [activityId, openId, handler, 1]
          )
        } else {
          const lastRequestTime = formatDate(handlerRecord.gmt_modified).getTimestamp()
          const now = Date.now()

          if (now - lastRequestTime < rate) {
            return resultsModel.error(CODE_TYPES.SYSTEM_ERROR, '请求过于频繁，请稍后再试~')
          } else {
            await context.cloud.dataspace.executeSql(
              `update ${recordTableName} set gmt_modified = ? where activity_id = ? and open_id = ? and handler = ?`,
              [Date.now(), activityId, openId, handler]
            )
          }
        }
      } catch (error) {
        console.log('error', error)
        recordErrorLog(context, baseInfos, error.toString(), error.stack)
        // 云告警
        cloundAlarm(context, error.toString())
        return resultsModel.error(CODE_TYPES.SYSTEM_ERROR)
      }

      return method.apply(target, [context, baseInfos, services, preCheckData])
    }
  }
}
